// worker类，用于处理多线程任务
class AsaiWorker {
    // 存储 worker 脚本的路径
    private workerScript: string;
    // 最大 worker 数量
    private maxWorkers: number;
    // 任务队列，存储待执行的任务
    private taskQueue: any[] = [];
    // 存储 worker 及其状态的映射
    private workers: Map<any, boolean> = new Map();
    // 存储任务 ID 和对应的任务结果处理函数
    private taskMap: Map<number, any> = new Map();
    // 任务 ID 计数器
    private taskId: number = 0;

    /**
     * AsaiWorker 类的构造函数，用于初始化类的属性。
     * @param {string} workerScript - worker 脚本的路径。
     * @param {number} [maxWorkers=navigator.hardwareConcurrency || 4] - 最大 worker 数量，默认为设备的硬件并发数或 4。
     */
    constructor(
        workerScript: string,
        maxWorkers: number = navigator.hardwareConcurrency || 4
    ) {
        this.workerScript = workerScript;
        this.maxWorkers = maxWorkers;
    }

    /**
     * 执行任务的方法，将任务添加到任务队列并开始处理。
     * @param {any} taskData - 任务数据。
     * @returns {Promise<any>} - 返回一个 Promise，当任务完成时解析为任务结果。
     */
    async execute(taskData: any): Promise<any> {
        return new Promise((resolve, reject) => {
            // 生成唯一的任务 ID
            const taskId = this.taskId++;
            // 将任务添加到任务队列
            this.taskQueue.push({ taskId, taskData });
            // 存储任务 ID 和对应的结果处理函数
            this.taskMap.set(taskId, { resolve, reject });
            // 处理下一个任务
            this._processNext();
        });
    }

    /**
     * 创建一个新的 worker 实例。
     * @returns {any} - 返回新创建的 worker 实例。
     */
    private _createWorker(): any {
        // 创建一个新的 worker 实例
        const worker = new Worker(this.workerScript, { type: 'module' });
        // 监听 worker 的消息事件
        worker.onmessage = (e: any) => {
            // 从消息中获取任务 ID、结果和错误信息
            const { taskId, result, error } = e.data;
            // 获取任务对应的结果处理函数
            const task = this.taskMap.get(taskId);
            if (task) {
                if (error) {
                    // 如果有错误，拒绝任务
                    task.reject(error);
                } else {
                    // 如果没有错误，解析任务结果
                    task.resolve(result);
                }
                // 从任务映射中删除已完成的任务
                this.taskMap.delete(taskId);
            }
            // 从 worker 映射中删除已完成任务的 worker
            this.workers.delete(worker);
            // 终止 worker 实例
            worker.terminate();
            // 处理下一个任务
            this._processNext();
        };
        // 监听 worker 的错误事件
        worker.onerror = (e: any) => {
            console.error('Worker error:', e);
            // 从 worker 映射中删除出错的 worker
            this.workers.delete(worker);
            // 创建一个新的 worker 实例
            this._createWorker();
        };
        // 将新创建的 worker 添加到 worker 映射中
        this.workers.set(worker, true);
        return worker;
    }

    /**
     * 处理任务队列中的下一个任务。
     */
    private _processNext() {
        // 当任务队列不为空且 worker 数量小于最大 worker 数量时
        while (
            this.taskQueue.length > 0 &&
            this.workers.size < this.maxWorkers
        ) {
            // 从任务队列中取出一个任务
            const task = this.taskQueue.shift();
            // 创建一个新的 worker 实例
            const worker = this._createWorker();
            // 向 worker 发送任务消息
            worker.postMessage({ taskId: task.taskId, data: task.taskData });
        }
    }

    /**
     * 终止所有正在运行的 worker 并清空任务队列。
     */
    terminateAll() {
        // 终止所有 worker 实例
        this.workers.forEach((_, worker) => worker.terminate());
        // 清空 worker 映射
        this.workers.clear();
        // 清空任务队列
        this.taskQueue = [];
    }
}

// api类，用于处理网络请求
class AsaiApi {
    // 基础 URL，用于网络请求
    private baseURL: string;
    // 可能包含额外配置或工具的对象
    private ujt: any;
    // 拦截器对象，包含请求拦截器和响应拦截器数组
    private interceptors: { request: any[]; response: any[] } = {
        request: [],
        response: [],
    };
    // 默认请求配置
    private defaultConfig: any = {
        headers: { 'Content-Type': 'application/json' },
        cache: 'reload', // reload或no-cache 强制向服务端验证；no-store 禁止缓存；
        timeout: 10000,
    };
    private totalApi: number = 0;

    /**
     * AsaiApi 类的构造函数，用于初始化类的属性。
     * @param {any} [params={}] - 包含初始化参数的对象。
     * @param {string} [params.baseURL] - 基础 URL，用于网络请求。
     * @param {any} [params.ujt] - 可能包含额外配置或工具的对象。
     */
    constructor(params: any = {}) {
        this.baseURL = params.baseURL;
        this.ujt = params.ujt;
    }

    /**
     * 发起网络请求的方法，支持请求和响应拦截器。
     * @param {string} url - 请求的 URL。
     * @param {any} [opt={}] - 请求配置选项。
     * @returns {Promise<any>} - 返回一个 Promise，当请求完成时解析为响应数据。
     */
    async api(url: string, opt: any = {}): Promise<any> {
        let currentTime: number = 0;
        let currentId: number = 0;
        if (this.ujt?.$global?.sys?.onconsole) {
            this.totalApi++;
            this.totalApi > 10000 && (this.totalApi = 0);
            currentId = this.totalApi;
            currentTime = Date.now() % 10000000;
        }

        // 创建一个 AbortController 用于处理请求超时
        const controller = new AbortController();
        const signal = controller.signal;
        // 设置请求超时时间
        const timeoutId = setTimeout(
            () => controller.abort(),
            opt.timeout || this.defaultConfig.timeout
        );
        try {
            const mergedConfig: any = {
                url: this.baseURL + url,
            };
            if (opt.body instanceof FormData) {
                mergedConfig.opt = opt;
            } else {
                // 合并默认配置和用户传入的配置
                mergedConfig.opt = {
                    ...this.defaultConfig,
                    ...opt,
                    signal,
                    headers: {
                        ...this.defaultConfig.headers,
                        ...opt.headers,
                    },
                };
            }
            currentTime &&
                this.ujt?.$fn?.lo?.(2, 'Req' + currentId, mergedConfig);
            // 初始化请求链，包含请求 URL 和配置
            let requestChain = Promise.resolve(mergedConfig);
            // 依次执行请求拦截器
            this.interceptors.request.forEach((interceptor) => {
                requestChain = requestChain.then((args) => interceptor(args));
            });
            // 获取最终的请求 URL 和配置
            const { url: finalUrl, opt: finalConfig } = await requestChain;
            // 发起网络请求
            const response = await fetch(finalUrl, finalConfig);
            // 清除超时定时器
            clearTimeout(timeoutId);
            // 解析响应数据
            const data = await this._parseResponse(response);
            // 初始化响应链，包含解析后的响应数据
            let responseChain = Promise.resolve(this._getRes(data, opt));
            // 依次执行响应拦截器
            this.interceptors.response.forEach((interceptor) => {
                responseChain = responseChain.then((res) => {
                    currentTime &&
                        this.ujt?.$fn?.lo?.(
                            3,
                            'Res' +
                                currentId +
                                ' ' +
                                ((Date.now() % 10000000) - currentTime) +
                                'ms',
                            res
                        );
                    return interceptor(res);
                });
            });
            return responseChain;
        } catch (error) {
            // 清除超时定时器
            clearTimeout(timeoutId);
            // 处理请求错误
            throw this._handleError(error);
        }
    }

    /**
     * 发起 GET 请求的方法。
     * @param {string} url - 请求的 URL。
     * @param {any} [params={}] - 请求参数。
     * @param {any} [opt={}] - 请求配置选项。
     * @returns {Promise<any>} - 返回一个 Promise，当请求完成时解析为响应数据。
     */
    apiGet(url: string, params: any = {}, opt: any = {}): Promise<any> {
        // 将请求参数转换为查询字符串
        const query = new URLSearchParams(params).toString();
        // 处理请求参数
        const tmpquery = this._getReq(query, opt);
        return this.api(`${url}${tmpquery ? '?' + tmpquery : ''}`, {
            ...opt,
            method: 'GET',
        });
    }

    /**
     * 发起 POST 请求的方法。
     * @param {string} url - 请求的 URL。
     * @param {any} data - 请求数据。
     * @param {any} [opt={}] - 请求配置选项。
     * @returns {Promise<any>} - 返回一个 Promise，当请求完成时解析为响应数据。
     */
    apiPost(url: string, data: any, opt: any = {}): Promise<any> {
        return this.api(url, {
            ...opt,
            method: 'POST',
            body:
                data instanceof FormData
                    ? data
                    : this._stringifyData(this._getReq(data, opt), opt.headers),
        });
    }

    /**
     * 发起文件上传请求的方法。
     * @param {string} url - 请求的 URL。
     * @param {any} file - 要上传的文件。
     * @param {any} opt - 请求配置选项。
     * @returns {Promise<any>} - 返回一个 Promise，当请求完成时解析为响应数据。
     */
    apiUpload(url: string, file: any, opt: any): Promise<any> {
        // 创建一个 FormData 对象用于上传文件
        const formData = new FormData();
        formData.append('file', file);
        return this.apiPost(url, formData, {
            ...opt,
        });
    }

    /**
     * 发起文件下载请求的方法。
     * @param {string} url - 请求的 URL。
     * @param {string} filename - 下载文件的文件名。
     * @returns {Promise<void>} - 返回一个 Promise，当请求完成时表示文件下载完成。
     */
    apiDownload(url: string, filename: string): Promise<void> {
        return this.apiGet(url, null, { responseType: 'blob' }).then(
            (blob: any) => {
                // 创建一个 a 标签用于下载文件
                const link = document.createElement('a');
                link.href = URL.createObjectURL(blob);
                link.download = filename;
                // 模拟点击 a 标签触发下载
                link.click();
            }
        );
    }

    /**
     * 处理请求参数的方法，可能进行加密等操作。
     * @param {any} reqdata - 请求数据。
     * @param {any} opt - 请求配置选项。
     * @returns {any} - 返回处理后的请求数据。
     */
    private _getReq(reqdata: any, opt: any): any {
        if (
            opt?.mm &&
            this.ujt?.$fn?.AsCode?.asdecode &&
            this.ujt?.$global?.code?.pri &&
            reqdata
        ) {
            // 对请求数据进行加密处理
            reqdata = this.ujt.$fn.AsCode.asencode(
                typeof reqdata === 'string' ? reqdata : JSON.stringify(reqdata),
                this.ujt.$global.code.pri
            );
        }
        return reqdata;
    }

    /**
     * 处理响应数据的方法，可能进行解密等操作。
     * @param {any} res - 响应数据。
     * @param {any} opt - 请求配置选项。
     * @returns {any} - 返回处理后的响应数据。
     */
    private _getRes(res: any, opt: any): any {
        if (
            opt?.mm &&
            this.ujt?.$fn?.AsCode?.asdecode &&
            this.ujt?.$global?.code?.pri &&
            res?.data &&
            typeof res.data === 'string'
        ) {
            // 对响应数据进行解密处理
            res.data = this.ujt.$fn.AsCode.asdecode(
                res.data,
                this.ujt.$global.code.pri
            );
            try {
                // 尝试将解密后的数据解析为 JSON 对象
                res.data = JSON.parse(res.data);
            } catch (err) {}
        }
        return res;
    }

    /**
     * 解析响应数据的方法，根据响应的 Content-Type 进行不同的处理。
     * @param {any} response - 响应对象。
     * @returns {Promise<any>} - 返回一个 Promise，当解析完成时解析为响应数据。
     */
    private _parseResponse(response: any): Promise<any> {
        // 获取响应的 Content-Type
        const contentType = response.headers.get('content-type');
        if (contentType?.includes('application/json')) {
            // 如果是 JSON 类型，解析为 JSON 对象
            return response.json();
        }
        if (contentType?.includes('text/')) {
            // 如果是文本类型，解析为文本
            return response.text();
        }
        // 其他类型返回二进制数据
        return response.blob();
    }

    /**
     * 序列化请求数据的方法，根据请求头的 Content-Type 进行不同的处理。
     * @param {any} data - 请求数据。
     * @param {any} headers - 请求头。
     * @returns {any} - 返回序列化后的请求数据。
     */
    private _stringifyData(data: any, headers: any): any {
        const contentType = headers?.['Content-Type'];
        if (data instanceof FormData) return data;
        if (typeof data === 'string') return data;
        if (contentType === 'application/json' || typeof data === 'object')
            return JSON.stringify(data);
        return String(data);
    }

    /**
     * 处理请求错误的方法，根据错误类型返回不同的错误信息。
     * @param {any} error - 错误对象。
     * @returns {any} - 返回处理后的错误信息。
     */
    private _handleError(error: any): any {
        if (error.name === 'AbortError') {
            return { code: 504, message: 'Request Timeout' };
        }
        return { code: 500, message: error.message || 'Network Error' };
    }

    /**
     * 添加请求拦截器的方法。
     * @param {any} interceptor - 请求拦截器函数。
     */
    ictReq(interceptor: any) {
        this.interceptors.request.push(interceptor);
    }

    /**
     * 添加响应拦截器的方法。
     * @param {any} interceptor - 响应拦截器函数。
     */
    ictRes(interceptor: any) {
        this.interceptors.response.push(interceptor);
    }
}

// ws类
class AsaiWs {
    // WebSocket 名称
    private wsname: string;
    // 是否使用 worker 处理 WebSocket 连接
    private wsworker: boolean;
    // 是否使用安全的 WebSocket 连接
    private wssec: boolean;
    // WebSocket 连接的 URL
    private wsurl: string;
    // 可能包含额外配置或工具的对象
    private ujt: any;
    // 基础 URL
    private baseURL: string;
    // 重连尝试次数
    private reconnectAttempts: number = 0;
    // 最大重连延迟时间
    private maxReconnectDelay: number = 0;
    // 消息队列，存储待发送的消息
    private messageQueue: string[] = [];
    // 是否正在发送消息的标志
    private isSending: boolean = false;
    // 存储消息任务的映射
    private wstaskMap: Map<string, any> = new Map();
    // 清理超时任务的定时器
    private cleanupInterval: ReturnType<typeof setInterval>;
    // 多线程状态
    private workerState: boolean = false;
    private totalWs: number = 0;

    /**
     * AsaiWs 类的构造函数，用于初始化类的属性。
     * @param {any} [params={}] - 包含初始化参数的对象。
     * @param {string} [params.wsname] - WebSocket 名称。
     * @param {boolean} [params.wsworker] - 是否使用 worker 处理 WebSocket 连接。
     * @param {boolean} [params.wssec] - 是否使用安全的 WebSocket 连接。
     * @param {string} [params.wsurl] - WebSocket 连接的 URL。
     * @param {any} [params.ujt] - 可能包含额外配置或工具的对象。
     * @param {string} [params.baseURL] - 基础 URL。
     */
    constructor(params: any = {}) {
        this.wsname = params.wsname;
        this.wsworker = params.wsworker;
        this.wssec = params.wssec;
        this.wsurl = params.wsurl;
        this.ujt = params.ujt;
        this.baseURL = params.baseURL;

        if (this.ujt.$global.link?.ws?.[this.wsname]?.config?.tmdeltask) {
            // 定时清理超时的消息任务
            this.cleanupInterval = setInterval(() => {
                if (this.wstaskMap.size) {
                    const now = Date.now();
                    this.wstaskMap.forEach((task, key) => {
                        if (
                            !task.type &&
                            task.timestamp &&
                            now - task.timestamp >
                                this.ujt.$global.link?.ws?.[this.wsname]?.config
                                    ?.tmdeltask /
                                    2
                        ) {
                            this.wstaskMap.delete(key);
                        }
                    });
                }
            }, this.ujt.$global.link?.ws?.[this.wsname]?.config?.tmdeltask);
        }
    }

    /**
     * 生成唯一 ID 的方法。
     * @param {string} [startsWord=''] - ID 的起始字符串。
     * @param {number} [index=0] - 索引值。
     * @param {number} [hex=32] - 十六进制位数。
     * @returns {string} - 返回生成的唯一 ID。
     */
    Uuid(startsWord = '', index = 0, hex = 32): string {
        const buffer = [
            Date.now().toString(36).slice(-9),
            index.toString(36),
            startsWord.slice(-3),
            crypto
                .getRandomValues(new Uint8Array(6))
                .reduce((acc, val) => acc + (val & 0x0f).toString(hex), ''),
        ];
        return buffer.join('').slice(0, 16);
    }

    /**
     * 发送消息的方法，将消息转换为字符串并调用 wsSendMsg 方法发送。
     * @param {any} msg - 要发送的消息。
     */
    wsSend(msg: any) {
        if (typeof msg === 'object') {
            msg = JSON.stringify(msg);
        }
        this.wsSendMsg(msg);
    }

    /**
     * 发起 WebSocket API 请求的方法，为消息添加唯一 ID 并监听响应。
     * @param {any} msg - 要发送的消息。
     * @returns {Promise<any>} - 返回一个 Promise，当收到响应时解析为响应数据。
     */
    wsApi(msg: any): Promise<any> {
        return new Promise((resolve, reject) => {
            let currentTime: number = 0;
            if (this.ujt?.$global?.sys?.onconsole) {
                currentTime = Date.now() % 10000000;
            }
            let msgdata: any;
            try {
                if (msg === 'ping') {
                    msgdata = 'ping';
                } else if (!msg) {
                    // 如果消息为空，生成一个包含唯一 ID 的消息
                    msgdata = { id: this.Uuid('ws') };
                    msg = JSON.stringify(msgdata);
                } else if (typeof msg === 'object') {
                    // 如果消息是对象，复制消息并添加唯一 ID
                    msgdata = { ...msg };
                    if (!msgdata?.id) {
                        msgdata.id = this.Uuid('ws');
                    }
                    msg = JSON.stringify(msgdata);
                } else {
                    // 如果消息是字符串，解析为对象并添加唯一 ID
                    msgdata = JSON.parse(msg);
                    if (!msgdata?.id) {
                        msgdata.id = this.Uuid('ws');
                        msg = JSON.stringify(msgdata);
                    }
                }
            } catch (err) {}
            // 监听消息响应
            this.wsWatchDo(msgdata, (res: any) => {
                if (currentTime) {
                    currentTime = (Date.now() % 10000000) - currentTime;
                    this.ujt?.$global?.sys?.onconsole &&
                        this.ujt?.$fn?.lo?.(
                            5,
                            'wsGet:' + currentTime + 'ms',
                            res
                        );
                }
                resolve(res);
            });
        });
    }

    /**
     * 监听消息响应的方法，发送消息并存储回调函数。
     * @param {any} msgdata - 消息数据。
     * @param {any} callback - 响应回调函数。
     */
    wsWatch(msgdata: any, callback: any) {
        this.ujt?.$global?.sys?.onconsole &&
            this.ujt?.$fn?.lo?.(3, 'wsWatch', msgdata);
        this.wsWatchDo(msgdata, callback);
    }
    wsWatchDo(msgdata: any, callback: any) {
        // 获取消息的唯一键
        const key = this.getKeyByData(msgdata);
        let taskdata: any = {};
        if (msgdata !== 'ping') {
            if (typeof msgdata == 'object' && msgdata?.id) {
                taskdata = { type: 0, timestamp: Date.now() };
            } else {
                taskdata = { type: 1 };
            }
        }
        // 存储消息任务和回调函数
        this.wstaskMap.set(key, {
            callback,
            ...taskdata,
        });
        // 发送消息
        this.wsSend(msgdata);
    }

    /**
     * 取消监听消息响应的方法，发送取消消息并从任务映射中删除任务。
     * @param {any} msgdata - 消息数据。
     */
    wsWatchOff(msgdata: any) {
        this.ujt?.$global?.sys?.onconsole &&
            this.ujt?.$fn?.lo?.(
                6,
                'wsWatchOff:' + this.wstaskMap.size,
                msgdata
            );
        // 如果消息没有 off 属性，添加 off 属性
        !msgdata.off && (msgdata.off = 1);
        // 发送取消消息
        this.wsSend(msgdata);
        // 获取消息的唯一键
        const key = this.getKeyByData(msgdata);
        // 从任务映射中获取任务
        const task = this.wstaskMap.get(key);
        if (task) {
            // 如果任务存在，从任务映射中删除任务
            this.wstaskMap.delete(key);
        }
    }

    /**
     * 处理收到的消息的方法，根据消息键查找任务并执行回调函数。
     * @param {any} msgdata - 消息数据。
     */
    wsWatchWork(msgdata: any) {
        // 获取消息的唯一键
        const key = this.getKeyByData(msgdata);
        // 从任务映射中获取任务
        const task = this.wstaskMap.get(key);
        if (task) {
            // 如果任务存在，执行回调函数
            task.callback(msgdata);
            if (!task.type) {
                // 如果任务类型为 0，从任务映射中删除任务
                this.ujt?.$global?.sys?.onconsole &&
                    this.ujt?.$fn?.lo?.(
                        3,
                        'wsDelete:' + this.wstaskMap.size,
                        key
                    );
                this.wstaskMap.delete(key);
            }
            //  else {
            //     this.ujt?.$global?.sys?.onconsole && this.ujt?.$fn?.lo?.(3, 'Watch', key);
            // }
        }
    }

    /**
     * 发送消息的异步方法，将消息添加到消息队列并依次发送。
     * @param {string} msg - 要发送的消息。
     */
    async wsSendMsg(msg: string) {
        if (msg === 'ping') {
            await this.sendSingleMessage(msg);
        } else {
            // 将消息添加到消息队列
            this.messageQueue.push(msg);
            if (!this.isSending) {
                // 如果没有正在发送消息，开始发送消息
                this.isSending = true;
                while (this.messageQueue.length > 0) {
                    // 从消息队列中取出一个消息
                    const nextMsg: any = this.messageQueue.shift();
                    if (this.ujt?.$global?.sys?.onconsole) {
                        this.totalWs++;
                        this.totalWs > 10000 && (this.totalWs = 0);
                        this.ujt?.$fn?.lo?.(
                            4,
                            'wsSend' +
                                this.totalWs +
                                ':' +
                                this.messageQueue.length,
                            nextMsg
                        );
                    }
                    // 发送单个消息
                    await this.sendSingleMessage(nextMsg);
                }
                // 发送完成，标记为未发送状态
                this.isSending = false;
            }
        }
    }

    /**
     * 发送单个消息的方法，根据配置选择使用 worker 或直接发送。
     * @param {string} msg - 要发送的消息。
     * @returns {Promise<void>} - 返回一个 Promise，当消息发送完成时解析。
     */
    sendSingleMessage(msg: string): Promise<void> {
        return new Promise((resolve, reject) => {
            this.init()
                .then(() => {
                    if (this.wsworker) {
                        // 如果使用 worker，通过 worker 发送消息
                        if (
                            typeof this.ujt.$fn.workers[this.wsname]?.instance
                                ?.postMessage === 'function'
                        ) {
                            this.ujt.$fn.workers[
                                this.wsname
                            ]?.instance?.postMessage({
                                type: 'send',
                                data: msg,
                            });
                            resolve();
                        } else {
                            reject();
                        }
                    } else {
                        if (
                            this.ujt.$fn.ws[this.wsname].socket?.readyState ===
                            WebSocket.OPEN
                        ) {
                            // 如果 WebSocket 连接已打开，直接发送消息
                            this.ujt.$fn.ws[this.wsname].socket.send(msg);
                            if (
                                this.ujt.$global.link.ws[this.wsname]?.config
                                    ?.resend
                            ) {
                                this.ujt.$global.link.ws[
                                    this.wsname
                                ].config.resend = 0;
                            }
                            resolve();
                        } else {
                            if (
                                this.ujt.$global.link.ws[this.wsname]?.config
                                    ?.resendmax &&
                                this.ujt.$global.link.ws[this.wsname].config
                                    ?.resend <=
                                    this.ujt.$global.link.ws[this.wsname].config
                                        ?.resendmax
                            ) {
                                // 如果发送次数未达到最大次数，重新发送消息
                                this.wsSendMsg(msg);
                                this.ujt.$global.link.ws[this.wsname].config
                                    .resend++;
                                resolve();
                            } else {
                                this.ujt?.$global?.sys?.onconsole &&
                                    this.ujt?.$fn?.lo?.(
                                        5,
                                        'Err',
                                        this.wsname,
                                        this.ujt.$global.link.ws[this.wsname]
                                            .config.resend,
                                        this.ujt.$global.link.ws[this.wsname]
                                            .config?.resendmax
                                    );
                                // 如果发送次数达到最大次数，拒绝 Promise
                                reject(new Error('Max send attempts reached'));
                            }
                        }
                    }
                })
                .catch(reject);
        });
    }

    /**
     * 根据消息数据获取唯一键的方法。
     * @param {any} msgdata - 消息数据。
     * @returns {string} - 返回唯一键。
     */
    getKeyByData(msgdata: any): string {
        if (msgdata === 'ping' || msgdata === 'pong') return 'pong';
        return msgdata?.id || msgdata?.ty;
    }

    /**
     * 创建新的 worker 实例的方法。
     * @param {any} fw - worker 配置对象。
     * @param {any} cb - 回调函数。
     */
    newWorker(fw: any, cb: any) {
        try {
            if (typeof Worker !== 'undefined' && fw.id) {
                if (!fw.workers[fw.id]) {
                    // 如果 worker 实例不存在，创建一个新的 worker 实例
                    fw.workers[fw.id] = {
                        instance: new Worker(
                            window.URL.createObjectURL(
                                new Blob([
                                    `eval(${fw.fn.toString()})(${JSON.stringify(
                                        fw.params
                                    )},this,'')`,
                                ])
                            )
                        ),
                        callbacks: new Set(),
                    };
                    // 监听 worker 实例的消息事件
                    fw.workers[fw.id].instance.onmessage = (e: any) => {
                        fw.workers[fw.id].callbacks.forEach((callback: any) => {
                            callback(e.data);
                        });
                    };
                }
                // 添加回调函数到 worker 实例的回调集合中
                fw.workers[fw.id].callbacks.add(cb);
            } else {
                // 如果不支持 worker，直接执行函数
                fw.fn(fw.params, '', cb);
            }
        } catch (err) {
            console.error('Worker creation error:', err);
        }
    }

    /**
     * 初始化 WebSocket worker 的方法。
     * @param {string} url - WebSocket 连接的 URL。
     * @param {any} wscb - 回调函数。
     */
    initWsWorker(url: string, wscb: any) {
        this.newWorker(
            {
                fn: function (params: any, wk: any, cb: any) {
                    const worktaskws: any = {};
                    function deonmessage(
                        msg: any,
                        fn: any,
                        taskws: any = {},
                        de: any
                    ) {
                        try {
                            const edata = JSON.parse(msg);
                            // 增加ws的de来标识是否启用前端过滤相同信息的操作
                            if (!de || !edata?.ty) {
                                fn(edata);
                            } else {
                                const ekey = edata?.ty;
                                if (!taskws[ekey]) {
                                    // 如果消息类型不存在，创建新的任务
                                    taskws[ekey] = {
                                        s: msg,
                                        v: edata,
                                        t: 1,
                                    };
                                } else {
                                    if (taskws[ekey].s === msg) {
                                        if (taskws[ekey].t) {
                                            // 如果消息内容相同，标记为已处理
                                            taskws[ekey].t = 0;
                                        }
                                    } else {
                                        // 如果消息内容不同，更新任务信息
                                        taskws[ekey].s = msg;
                                        taskws[ekey].v = edata;
                                        if (!taskws[ekey].t) {
                                            taskws[ekey].t = 1;
                                        }
                                    }
                                }
                                if (taskws[ekey]?.t) {
                                    // 如果任务未处理，发送消息
                                    fn(taskws[ekey]?.v);
                                }
                            }
                        } catch (err) {
                            // 如果解析出错，直接发送消息
                            fn(msg);
                        }
                    }
                    /**
                     * 处理 WebSocket 消息的方法。
                     * @param {any} e - 消息事件对象。
                     * @param {any} fnSend - 发送消息的函数。
                     */
                    function wsonmessage(e: any, fnSend: any) {
                        if (e?.data) {
                            if (e.data === 'pong') {
                                // 如果收到 pong 消息，直接发送
                                fnSend(e.data);
                            } else if (typeof e.data === 'string') {
                                deonmessage(
                                    e.data,
                                    fnSend,
                                    worktaskws,
                                    params.de
                                );
                            }
                        }
                    }

                    /**
                     * 关闭 WebSocket 连接并终止 worker 的方法。
                     */
                    function wkclose() {
                        socket.close();
                        socket = null;
                        wk.postMessage('onclose');
                        wk.terminate();
                    }

                    let socket: any =
                        this.wssec && this.ujt.$global.code.token
                            ? new WebSocket(
                                  params.url,
                                  this.ujt.$global.code.token
                              )
                            : new WebSocket(params.url);
                    // 监听 WebSocket 消息事件
                    socket.onmessage = (e: any) => {
                        wsonmessage(e, wk.postMessage);
                    };
                    // 监听 WebSocket 关闭事件
                    socket.onclose = (e: any) => {
                        wk.postMessage('onclose');
                    };
                    // 监听 WebSocket 错误事件
                    socket.onerror = (e: any) => {
                        wk.postMessage('onerror');
                    };
                    // 监听 WebSocket 打开事件
                    socket.onopen = (e: any) => {
                        socket.open = 1;
                        wk.postMessage('onopen');
                    };

                    // 监听 worker 的消息事件
                    wk.onmessage = (e: any) => {
                        try {
                            if (socket?.open) {
                                if (e?.data?.type === 'close') {
                                    // 如果收到关闭消息，关闭连接并终止 worker
                                    wkclose();
                                } else if (e?.data?.type === 'send') {
                                    // 如果收到发送消息，发送消息
                                    socket.send(e?.data?.data || '');
                                }
                            } else {
                                // 如果连接未打开，关闭连接并终止 worker
                                wkclose();
                            }
                        } catch (err) {
                            wkclose();
                        }
                    };
                },
                params: {
                    url,
                    de: this.ujt.$global.link.ws[this.wsname].config.de,
                },
                id: this.wsname,
                workers: this.ujt.$fn.workers,
            },
            (res: any) => {
                if (res && res !== 'null') {
                    // 如果收到有效响应，执行回调函数
                    wscb(res);
                }
            }
        );
    }

    /**
     * 初始化 WebSocket 连接的方法。
     * @returns {Promise<any>} - 返回一个 Promise，当连接初始化完成时解析为 ujt 对象。
     */
    init(): Promise<any> {
        const normaltaskws: any = {};
        function deonmessage(msg: any, fn: any, taskws: any = {}, de: any) {
            try {
                const edata = JSON.parse(msg);
                // 增加ws的de来标识是否启用前端过滤相同信息的操作
                if (!de || !edata?.ty) {
                    fn(edata);
                } else {
                    const ekey = edata?.ty;
                    if (!taskws[ekey]) {
                        // 如果消息类型不存在，创建新的任务
                        taskws[ekey] = {
                            s: msg,
                            v: edata,
                            t: 1,
                        };
                    } else {
                        if (taskws[ekey].s === msg) {
                            if (taskws[ekey].t) {
                                // 如果消息内容相同，标记为已处理
                                taskws[ekey].t = 0;
                            }
                        } else {
                            // 如果消息内容不同，更新任务信息
                            taskws[ekey].s = msg;
                            taskws[ekey].v = edata;
                            if (!taskws[ekey].t) {
                                taskws[ekey].t = 1;
                            }
                        }
                    }
                    if (taskws[ekey]?.t) {
                        // 如果任务未处理，发送消息
                        fn(taskws[ekey]?.v);
                    }
                }
            } catch (err) {
                // 如果解析出错，直接发送消息
                fn(msg);
            }
        }
        const that = this;
        return new Promise((resolve, reject) => {
            try {
                if (this.ujt.$ws[this.wsname]?.open) {
                    // 如果 WebSocket 连接已打开，直接解析 Promise
                    resolve(this.ujt);
                } else {
                    if (!this.wsurl.startsWith('ws')) {
                        // 如果浏览器不支持 WebSocket，拒绝 Promise
                        reject({
                            error:
                                this.wsurl +
                                ' is not a WebSocket (WS) address!',
                        });
                    } else if (!('WebSocket' in window)) {
                        // 如果浏览器不支持 WebSocket，拒绝 Promise
                        reject({ error: 'WebSocket is null!' });
                    }
                    if (this.wsworker) {
                        if (this.workerState) {
                            // 防止频繁重复请求
                            setTimeout(() => {
                                resolve(this.ujt);
                            }, 3000);
                        } else {
                            this.workerState = true;
                            // 如果使用 worker，初始化 WebSocket worker
                            this.initWsWorker(this.wsurl, (res: any) => {
                                if (res === 'onclose') {
                                    // 如果收到关闭消息，调用 onclose 方法
                                    onclose();
                                } else if (res === 'onerror') {
                                    // 如果收到错误消息，调用 onerror 方法
                                    onerror();
                                } else if (res === 'onopen') {
                                    // 如果收到打开消息，调用 onopen 方法并解析 Promise
                                    onopen();
                                    resolve(this.ujt);
                                } else {
                                    // 如果收到其他消息，调用 onmessagedo 方法
                                    onmessagedo(res);
                                }
                            });
                        }
                    } else {
                        if (!this.ujt.$fn.ws[this.wsname]) {
                            // 如果 WebSocket 实例不存在，创建一个新的实例
                            this.ujt.$fn.ws[this.wsname] = {};
                        }
                        this.ujt.$fn.ws[this.wsname].socket =
                            this.wssec && this.ujt.$global.code.token
                                ? new WebSocket(
                                      this.wsurl,
                                      this.ujt.$global.code.token
                                  )
                                : new WebSocket(this.wsurl);
                        // 监听 WebSocket 消息事件
                        this.ujt.$fn.ws[this.wsname].socket.onmessage =
                            onmessage;
                        // 监听 WebSocket 关闭事件
                        this.ujt.$fn.ws[this.wsname].socket.onclose = onclose;
                        // 监听 WebSocket 错误事件
                        this.ujt.$fn.ws[this.wsname].socket.onerror = onerror;
                        // 监听 WebSocket 打开事件
                        this.ujt.$fn.ws[this.wsname].socket.onopen = (
                            e: any
                        ) => {
                            onopen(e);
                            resolve(this.ujt);
                        };
                    }
                }
            } catch (err) {
                // 如果发生错误，调用 onerror 方法并拒绝 Promise
                onerror(err);
                reject(err);
            }
            /**
             * 处理 WebSocket 打开事件的方法。
             * @param {any} [e=null] - 事件对象。
             */
            function onopen(e: any = null) {
                if (!that.ujt.$ws[that.wsname]) {
                    // 如果 WebSocket 状态对象不存在，创建一个新的对象
                    that.ujt.$ws[that.wsname] = {};
                }
                // 标记 WebSocket 连接已打开
                that.ujt.$ws[that.wsname].open = true;
            }

            /**
             * 处理 WebSocket 消息事件的方法。
             * @param {any} e - 事件对象。
             */
            function onmessage(e: any) {
                // 处理消息数据
                deonmessage(
                    e.data,
                    onmessagedo,
                    normaltaskws,
                    that.ujt.$global.link.ws[that.wsname].config.de
                );
            }

            /**
             * 处理消息数据的方法。
             * @param {any} edata - 消息数据。
             */
            function onmessagedo(edata: any) {
                if (that.wstaskMap.size) {
                    // 有监听任务的时候在执行监听
                    try {
                        if (typeof edata === 'object') {
                            // 如果消息数据是对象，直接处理
                            that.wsWatchWork(edata);
                        } else {
                            // 如果消息数据是字符串，解析为对象后处理
                            that.wsWatchWork(JSON.parse(edata));
                        }
                    } catch (err) {
                        that.wsWatchWork(edata);
                    }
                }
            }

            /**
             * 处理 WebSocket 错误事件的方法。
             * @param {any} [e=null] - 事件对象。
             */
            function onerror(e: any = null) {
                if (that?.ujt?.$ws?.[that?.wsname]) {
                    // 标记 WebSocket 连接已关闭
                    that.ujt.$ws[that.wsname].open = false;
                    that.ujt.$global.stat[that.wsname] = 0;
                }
                that?.ujt?.$global?.msg?.fn({
                    type: 'err',
                    con:
                        that.ujt.$fn.lg('asai.hostmsg.error', that.wsname) ||
                        that.wsname + 'is error!',
                });
                // 拒绝 Promise
                // reject(e);
            }

            /**
             * 处理 WebSocket 关闭事件的方法。
             * @param {any} [e=null] - 事件对象。
             */
            function onclose(e: any = null) {
                if (that.ujt.$ws[that.wsname]) {
                    // 标记 WebSocket 连接已关闭
                    that.ujt.$ws[that.wsname].open = false;
                    that.ujt.$global.stat[that.wsname] = 0;
                }
                that.ujt.$global?.msg?.fn({
                    type: 'err',
                    con:
                        that.ujt.$fn.lg('asai.hostmsg.closed', that.wsname) ||
                        that.wsname + 'is close!',
                });
                // 调度重连
                scheduleReconnect();
            }

            /**
             * 调度重连的方法。
             */
            function scheduleReconnect() {
                if (that.maxReconnectDelay) {
                    const delay = Math.min(
                        1000 * Math.pow(2, that.reconnectAttempts),
                        that.maxReconnectDelay
                    );
                    // 延迟一段时间后重新初始化 WebSocket 连接
                    setTimeout(() => that.init(), delay);
                    // 增加重连尝试次数
                    that.reconnectAttempts++;
                }
            }
        });
    }
}

/**
 * 创建 AsaiModel 对象的工厂函数。
 * @param {string} [baseURL='./webmodel/'] - 基础 URL。
 * @returns {Object} - 返回包含 fetchPublic 方法的对象。
 */
function AsaiModel(baseURL: string = './webmodel/') {
    const fetchApi = new AsaiApi({
        baseURL,
    });

    /**
     * 发起公共资源请求的方法，递归获取目录下的所有资源。
     * @param {string} url - 请求的 URL。
     * @param {string} [params=''] - 请求参数。
     * @returns {Promise<any>} - 返回一个 Promise，当请求完成时解析为响应数据。
     */
    function fetchPublic(url, params = '') {
        return new Promise((resolve, reject) => {
            fetchApi
                ?.apiGet(url)
                .then((res) => {
                    Promise.all(
                        dfsFetch(
                            res,
                            url.substring(0, url.lastIndexOf('/') + 1) + params
                        )
                    )
                        .then(() => {
                            resolve(res);
                        })
                        .catch((err) => {
                            reject(err);
                        });
                })
                .catch((err) => {
                    reject(err);
                });
        });
    }

    /**
     * 深度优先搜索目录下所有资源的方法。
     * @param {any} res - 响应数据。
     * @param {string} dirpath - 目录路径。
     * @returns {any[]} - 返回包含所有请求 Promise 的数组。
     */
    function dfsFetch(res, dirpath) {
        const proAll: any = [];
        if (res?.dir?.length) {
            res.dir.forEach((el) => {
                const urlTmp = dirpath + el;
                const lastIndex = urlTmp.lastIndexOf('/');
                proAll.push(
                    fetchApi
                        ?.apiGet(urlTmp)
                        .then((tmpRes) => {
                            const filename = urlTmp.substring(lastIndex + 1);
                            res[filename.substring(0, filename.indexOf('.'))] =
                                tmpRes;
                            proAll.push(
                                Promise.all(
                                    dfsFetch(
                                        tmpRes,
                                        urlTmp.substring(0, lastIndex + 1)
                                    )
                                )
                            );
                        })
                        .catch((err) => {
                            console.error('Error fetching resource:', err);
                        })
                );
            });
        }
        return proAll;
    }

    return { fetchPublic };
}

// 导出 AsaiWorker、AsaiApi、AsaiWs 和 AsaiModel 类
export default { AsaiWorker, AsaiApi, AsaiWs, AsaiModel };
